home *** CD-ROM | disk | FTP | other *** search
- /* GIF Load/Save Source for WGT
- Free code
-
- Notes: There are now restrictions on the use of the GIF file format.
- Royalties must be paid to CompuServe if the program you have created
- is sold for profit. Freeware programs may use this code without
- any payments.
-
- Exact details can be obtained from CompuServe.
- */
-
-
- #include <stdlib.h>
- #include <stdio.h>
- #include <mem.h>
- #include <dos.h>
- #include <malloc.h>
- #include <wgt5.h>
-
-
- #define GOOD_READ 0
- #define BAD_FILE 1
- #define BAD_READ 2
- #define UNEXPECTED_EOF 3
- #define BAD_CODE 4
- #define BAD_FIRSTCODE 5
- #define BAD_ALLOC 6
- #define BAD_SYMBOLSIZE 7
-
- #define NO_CODE -1
-
- #define largest_code 4095
- #define table_size 5003
-
-
- typedef struct {
- signed char sig[6];
- unsigned short screenwidth, screendepth;
- unsigned char flags, background, aspect;
- } GIFHEADER;
-
- typedef struct {
- unsigned short left, top, width, depth;
- unsigned char flags;
- } IMAGEBLOCK;
-
- typedef struct {
- short width, depth, bits;
- short flags;
- short background;
- signed char palette[768];
- short (*setup)();
- short (*closedown)();
- short (*saveline)();
- short (*saveext)();
- } FILEINFO;
-
- typedef struct {
- signed char blocksize;
- signed char flags;
- unsigned short delay;
- signed char transparent_colour;
- signed char terminator;
- } CONTROLBLOCK;
-
- typedef struct {
- signed char blocksize;
- unsigned short left, top;
- unsigned short gridwidth, gridheight;
- signed char cellwidth, cellheight;
- signed char forecolour, backcolour;
- } PLAINTEXT;
-
- typedef struct {
- signed char blocksize;
- signed char applstring[8];
- signed char authentication[3];
- } APPLICATION;
-
- static char code_buffer[259];
- static FILEINFO fi;
- static block ptr;
- static int pixctr;
- static int maxctr;
- static short oldcode[table_size];
- static short currentcode[table_size];
- static char newcode[table_size];
- static short code_size;
- static short clear_code;
- static short eof_code;
- static short bit_offset;
- static short byte_offset;
- static short bits_left;
- static short max_code;
- static short free_code;
-
- void putline (block p, int n)
- {
- if (n >= 0 && n < fi.depth)
- memcpy (ptr + ((int)n * (int)fi.width) + 4, p, fi.width);
- }
-
-
- void putextension (FILE *fp)
- {
- PLAINTEXT pt;
- CONTROLBLOCK cb;
- APPLICATION ap;
- short c, n, i;
-
- fread (&c, 1, 1, fp);
- switch (c) {
- case 0x0001 : fread ((char *)&pt, 1, sizeof(PLAINTEXT), fp);
- do {
- if ((n = fgetc(fp)) != EOF)
- {
- for (i = 0; i < n; i++)
- fgetc (fp);
- }
- } while (n > 0 && n != EOF);
- break;
- case 0x0009 : fread ((char *)&cb, 1, sizeof(CONTROLBLOCK), fp);
- break;
- case 0x00fe : do {
- if ((n = fgetc (fp)) != EOF)
- {
- for (i = 0; i < n; i++)
- fgetc (fp);
- }
- } while (n > 0 && n != EOF);
- break;
- case 0x00ff : fread ((char *)&ap, 1, sizeof(APPLICATION), fp);
- do {
- if ((n = fgetc (fp)) != EOF)
- {
- for (i = 0; i < n; i++)
- fgetc (fp);
- }
- } while (n > 0 && n != EOF);
- break;
- default : if ((n = fgetc (fp)) != EOF)
- {
- for (i = 0; i < n; i++)
- fgetc (fp);
- }
- break;
- }
- }
-
-
- short unpackimage (FILE *fp, short bits)
- {
- short bits2;
- short codesize;
- short codesize2;
- short nextcode;
- short thiscode;
- short oldtoken;
- short currentcode;
- short oldcode;
- short bitsleft;
- short blocksize;
- short line = 0;
- short byte = 0;
- short pass = 0;
-
- char *p;
- char *q;
- char b[255];
- char *u;
- char *linebuffer;
-
- static char firstcodestack[4096];
- static char lastcodestack[4096];
- static short codestack[4096];
-
- static short wordmasktable[] = { 0x0000, 0x0001, 0x0003, 0x0007,
- 0x000f, 0x001f, 0x003f, 0x007f,
- 0x00ff, 0x01ff, 0x03ff, 0x07ff,
- 0x0fff, 0x1fff, 0x3fff, 0x7fff };
-
- static short inctable[] = { 8, 8, 4, 2, 0 };
- static short startable[] = { 0, 4, 2, 1, 0 };
-
- p = q = b;
- bitsleft = 8;
-
- if (bits < 2 || bits > 8)
- return (BAD_SYMBOLSIZE);
- bits2 = 1 << bits;
- nextcode = bits2 + 2;
- codesize2 = 1 << (codesize = bits + 1);
- oldcode = oldtoken = NO_CODE;
-
- if ((linebuffer = malloc (fi.width)) == NULL)
- return (BAD_ALLOC);
-
- /* loop until something breaks */
- for (;;) {
- if (bitsleft == 8) {
- if (++p >= q && (((blocksize = fgetc(fp)) < 1) ||
- (q=(p=b)+fread (b, 1, blocksize, fp)) < (b+blocksize))) {
- free (linebuffer);
- return (UNEXPECTED_EOF);
- }
- bitsleft = 0;
- }
- thiscode = *p;
- if ((currentcode = (codesize+bitsleft)) <= 8) {
- *p >>= codesize;
- bitsleft = currentcode;
- }
- else {
- if (++p >= q && (((blocksize = fgetc(fp)) < 1) ||
- (q=(p=b)+fread (b, 1, blocksize, fp)) < (b+blocksize))) {
- free (linebuffer);
- return (UNEXPECTED_EOF);
- }
- thiscode |= *p << (8 - bitsleft);
- if (currentcode <= 16)
- *p >>= (bitsleft = currentcode - 8);
- else {
- if (++p >= q && (((blocksize = fgetc(fp)) < 1) ||
- (q=(p=b)+fread (b, 1, blocksize, fp)) < (b+blocksize))) {
- free (linebuffer);
- return (UNEXPECTED_EOF);
- }
- thiscode |= *p << (16 - bitsleft);
- *p >>= (bitsleft = currentcode - 16);
- }
- }
- thiscode &= wordmasktable[codesize];
- currentcode = thiscode;
-
- if (thiscode == (bits2+1))
- break;
- if (thiscode > nextcode) {
- free (linebuffer);
- return (BAD_CODE);
- }
-
- if (thiscode == bits2) {
- nextcode = bits2 + 2;
- codesize2 = 1 << (codesize = (bits + 1));
- oldtoken = oldcode = NO_CODE;
- continue;
- }
-
- u = firstcodestack;
-
- if (thiscode == nextcode) {
- if (oldcode == NO_CODE) {
- free (linebuffer);
- return (BAD_FIRSTCODE);
- }
- *u++ = oldtoken;
- thiscode = oldcode;
- }
-
- while (thiscode >= bits2) {
- *u++ = lastcodestack [thiscode];
- thiscode = codestack[thiscode];
- }
-
- oldtoken = thiscode;
- do {
- linebuffer[byte++] = thiscode;
- if (byte >= fi.width) {
- putline (linebuffer, line);
- byte = 0;
- /* check for interlaced image */
- if (fi.flags & 0x40) {
- line += inctable[pass];
- if (line >= fi.depth)
- line = startable[++pass];
- } else ++line;
- }
- if (u <= firstcodestack)
- break;
- thiscode = *--u;
- } while (1);
-
- if (nextcode < 4096 && oldcode != NO_CODE) {
- codestack[nextcode] = oldcode;
- lastcodestack[nextcode] = oldtoken;
- if (++nextcode >= codesize2 && codesize < 12)
- codesize2 = 1 << ++codesize;
- }
- oldcode = currentcode;
- }
- free (linebuffer);
- return (GOOD_READ);
- }
-
-
- block wloadgif (char *filename, color pal[256])
- {
- GIFHEADER gh;
- IMAGEBLOCK iblk;
- int t;
- short b,c;
-
- if (wgtlibrary == NULL)
- {
- if ((libf = fopen (filename, "rb")) == NULL)
- return NULL;
- }
- else
- {
- if ((libf = fopen (wgtlibrary, "rb")) == NULL)
- return NULL;
- readheader ();
- findfile (filename);
- if (lresult == 1)
- fseek (libf, lfpos, SEEK_SET);
- if (checkpassword (password) == 0)
- {
- wsetmode (3);
- printf ("Incorrect password");
- exit (1);
- }
- }
-
- if ((wgtlibrary != NULL) & (lresult == 0)) goto lblkstop;
-
- if (fread((char *)&gh, 1, sizeof(GIFHEADER), libf) != sizeof(GIFHEADER) ||
- memcmp(gh.sig, "GIF", 3))
- {
- fclose (libf);
- return NULL;
- }
-
- /* get screen dimensions */
- fi.width = gh.screenwidth;
- fi.depth = gh.screendepth;
- fi.bits = (gh.flags & 0x0007) + 1;
- /* get colour map if there is one */
- if (gh.flags & 0x80) {
- c = 3 * (1 << ((gh.flags & 7) + 1));
- if (fread (pal, 1, c, libf) != c)
- {
- fclose (libf);
- return NULL;
- }
- }
- /* step through the blocks */
- while ((c=fgetc(libf))==',' || c=='!' || c==0) {
- /* if it's an image block */
- if (c == ',') {
- /* get the start of the image block */
- if (fread (&iblk, 1, sizeof(IMAGEBLOCK), libf) != sizeof(IMAGEBLOCK))
- {
- fclose (libf);
- return NULL;
- }
-
- /* get the image dimensions */
- fi.width = iblk.width;
- fi.depth = iblk.depth;
-
- /* get the local colour map if there is one */
- if (iblk.flags & 0x80) {
- b = 3 * (1 << ((iblk.flags & 0x0007) + 1));
- if (fread (pal, 1, b, libf) != c)
- {
- fclose (libf);
- return NULL;
- }
- fi.bits = (iblk.flags & 0x0007) + 1;
- }
-
- /* get the initial code size */
- if (fread (&c, 1, 1, libf) == 0)
- {
- fclose (libf);
- return NULL;
- }
-
- fi.flags = iblk.flags;
-
- if ( (ptr = malloc ( (int)fi.width * (int)fi.depth + 5) ) == NULL)
- {
- fclose (libf);
- return NULL;
- }
-
- for (b = 0; b < 256; b++)
- {
- pal[b].r >>= 2;
- pal[b].g >>= 2;
- pal[b].b >>= 2;
- }
- *(short *)ptr = fi.width;
- ptr += 2;
- *(short *)ptr = fi.depth;
- ptr -= 2;
- t = unpackimage (libf, c);
- if (t != GOOD_READ)
- {
- free (ptr);
- fclose (libf);
- return NULL;
- }
- else {
- fclose (libf);
- return ptr;
- }
- }
- else if (c == '!')
- putextension (libf);
- };
- lblkstop:
- ;
- fclose (libf);
- return ptr;
- }
-
-
- void init_table (short min_code_size)
- {
- short i;
-
- code_size = min_code_size + 1;
- clear_code = (1<<min_code_size);
- eof_code = clear_code + 1;
- free_code = clear_code + 2;
- max_code = (1 << code_size);
-
- for (i=0; i<table_size; i++)
- currentcode[i] = 0;
- }
-
-
- void flush (FILE *fp, short n)
- {
- fputc (n, fp);
- fwrite (code_buffer, 1, n, fp);
- }
-
-
- void write_code (FILE *fp, short code)
- {
- int temp;
-
- byte_offset = bit_offset >> 3;
- bits_left = bit_offset & 7;
-
- if (byte_offset >= 254) {
- flush (fp, byte_offset);
- code_buffer[0] = code_buffer[byte_offset];
- bit_offset = bits_left;
- byte_offset = 0;
- }
- if (bits_left > 0) {
- temp = ((int) code << bits_left) | code_buffer[byte_offset];
- code_buffer[byte_offset] = temp;
- code_buffer[byte_offset+1] = (temp >> 8);
- code_buffer[byte_offset+2] = (temp >> 16);
- } else {
- code_buffer[byte_offset] = code;
- code_buffer[byte_offset+1] = (code >> 8);
- }
- bit_offset += code_size;
- }
-
-
- short readpixel (void)
- {
- unsigned char pxl;
-
- pixctr++;
- if (pixctr > maxctr)
- return 9999;
- pxl = *ptr;
- ptr++;
- return (pxl);
- }
-
-
- void compressImage (FILE *fp, unsigned short min_code_size)
- {
- short prefix_code;
- short suffix_char;
- short hx, d;
-
- if (min_code_size < 2 || min_code_size > 9) {
- if (min_code_size == 1)
- min_code_size = 2;
- else return;
- }
-
- /* write initial code size */
- fputc (min_code_size, fp);
-
- /* initialize the encoder */
- bit_offset = 0;
- init_table (min_code_size);
- write_code (fp, clear_code);
- if ((suffix_char = readpixel()) == 9999)
- return;
-
- /* initialize the prefix */
- prefix_code = suffix_char;
-
- /* get a character to compress */
- while ((suffix_char = readpixel()) != 9999) {
- /* derive an index into the code table */
- hx = (prefix_code ^ (suffix_char << 5)) % table_size;
- d = 1;
-
- for (;;) {
- /* see if the code is in the table */
- if (currentcode[hx] == 0) {
- /* if not, put it there */
- write_code (fp, prefix_code);
- d = free_code;
-
- /* find the next free code */
- if (free_code <= largest_code) {
- oldcode[hx] = prefix_code;
- newcode[hx] = suffix_char;
- currentcode[hx] = free_code;
- free_code++;
- }
-
- /* expand the code size or scrap the table */
- if (d == max_code) {
- if (code_size < 12) {
- code_size++;
- max_code <<= 1;
- }
- else {
- write_code (fp, clear_code);
- init_table (min_code_size);
- }
- }
- prefix_code = suffix_char;
- break;
- }
- if (oldcode[hx] == prefix_code &&
- newcode[hx] == suffix_char)
- {
- prefix_code = currentcode[hx];
- break;
- }
- hx += d;
- d += 2;
- if (hx >= table_size)
- hx -= table_size;
- }
- }
-
- /* write the prefix code */
- write_code (fp, prefix_code);
-
- /* and the end of file code */
- write_code (fp, eof_code);
-
- /* flush the buffer */
- if (bit_offset > 0)
- flush (fp, (bit_offset+7)/8);
-
- /* write a zero length block */
- flush (fp, 0);
- }
-
-
- void wsavegif (char *filename, block image, color pal[256])
- {
- GIFHEADER gh;
- IMAGEBLOCK iblk;
- short b;
- FILE *fp;
- color p[256];
-
- if ((fp = fopen (filename, "wb")) == NULL)
- return;
-
- ptr = image + 4;
- memset ((char *)&gh, 0, sizeof(GIFHEADER));
- memcpy (gh.sig, "GIF87a", 6);
- gh.screenwidth = wgetblockwidth (image);
- gh.screendepth = wgetblockheight (image);
- gh.flags = 0xf7;
- fwrite((char *)&gh, 1, sizeof(GIFHEADER), fp);
-
- for (b = 0; b < 256; b++)
- {
- p[b].r = pal[b].r << 2;
- p[b].g = pal[b].g << 2;
- p[b].b = pal[b].b << 2;
- }
- fwrite (p, 1, 768, fp);
-
- memset ((char *)&iblk, 0, sizeof (IMAGEBLOCK));
- fputc(',', fp);
- iblk.left = 0;
- iblk.top = 0;
- iblk.width = gh.screenwidth;
- iblk.depth = gh.screendepth;
- iblk.flags = 0x7;
- fwrite ((char *)&iblk, 1, sizeof (IMAGEBLOCK), fp);
-
- pixctr = 0;
- maxctr = iblk.width * iblk.depth;
- compressImage (fp, 8);
-
- fputc (';', fp);
- fclose (fp);
- }
-